﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Web;
using System.Web.Mvc;
using BMS.ViewModels;
using BMS.Models.DataAccess;
using BMS.Utilities;
using BMS.Models;
using BMS.Models.BusinessLogic;
using MvcPaging;

namespace BMS.Controllers
{
    public class InvoiceController : Controller
    {
        private const int DefaultPageSize = 10;
        private InvoiceRepository invoiceRepository = new InvoiceRepository();
        private QuotationRepository quoteRepository = new QuotationRepository();
        private QuotationInvoiceModel quoteInvoiceModel = new QuotationInvoiceModel();
        private FMRepository fmRepository = new FMRepository();
        private ClientRepository clientRepository = new ClientRepository();
        private GeneralRepository generalRepository = new GeneralRepository();
        private CompanyRepository companyRepository = new CompanyRepository();
        private InvoiceDocument invoiceDocument = new InvoiceDocument();
        
        private List<QuotationModel> GetAllAvailableQuotaionsList()
        {
            List<QuotationModel> quoteList = quoteRepository.GetAllQuotations().OrderBy(x => x.QuotationNo).ToList();
            List<InvoiceItemModel> invoiceItemList = invoiceRepository.GetAllInvoiceItems();

            List<QuotationModel> tempList = new List<QuotationModel>();
            if (invoiceItemList.Count > 0)
            {
                foreach (QuotationModel qModel in quoteList)
                {
                    bool isFound = false;
                    foreach (InvoiceItemModel iItem in invoiceItemList)
                    {
                        if (iItem.QuotationNo == qModel.QuotationNo)
                        {
                            isFound = true;
                            break;
                        }
                    }

                    if (isFound == false)
                        tempList.Add(qModel);
                }
            }
            else
                tempList.AddRange(quoteList);

            return tempList;
        }
        
        //
        // GET: /Invoice/
        public ActionResult Index()
        {
            ViewBag.Message = "Invoice";

            quoteInvoiceModel.AvailableQuotaionsSelectedList = GetAllAvailableQuotaionsList();
            quoteInvoiceModel.RequestedQuotaionsSelectedList = new List<QuotationModel>();
            quoteInvoiceModel.invoiceModel = new InvoiceModel();
            quoteInvoiceModel.invoiceModel.InvoiceNo = "IN-" + DateTime.Today.ToString("yyMM") + "-" + invoiceRepository.GetNextInvoiceNo();
            quoteInvoiceModel.fmList = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList());
            quoteInvoiceModel.fmListForFiltering = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), true);
            quoteInvoiceModel.targetList = generalRepository.GetInvoiceTypesForDropDownList(Configuration.TargetToList);

            return View(quoteInvoiceModel);
        }

        [HttpPost]
        public ActionResult Index(QuotationInvoiceModel model, string add, string remove, string confirm, FormCollection formValue)
        {
            ViewBag.Message = "Invoice";
            String selectedFM = formValue["FMNameSV"];


            //Need to clear model state or it will interfere with the updated model
            ModelState.Clear();
            RestoreSavedState(model, selectedFM);
            if (!string.IsNullOrEmpty(add))
                AddQuotations(model, selectedFM);
            else if (!string.IsNullOrEmpty(remove))
                RemoveQuotations(model, selectedFM);
            else if (!string.IsNullOrEmpty(confirm))
            {
                List<QuotationModel> quotModelList = model.RequestedQuotaionsSelectedList;
                
                InvoiceModel newInvoice = new InvoiceModel();
                newInvoice.InvoiceNo = selectedFM + "-" + model.invoiceModel.InvoiceNo;
                newInvoice.InvoiceCreationDate = DateTime.Today;
                newInvoice.NoOfQuotations = quotModelList.Count;
                newInvoice.DNNo = model.invoiceModel.DNNo;

                if (newInvoice.DNNo != null)
                    newInvoice.isDebitNote = "Y";
                else
                {
                    newInvoice.isDebitNote = "N";
                    newInvoice.DNNo = "";
                }

                newInvoice.QuotNo = model.invoiceModel.QuotNo;

                if (newInvoice.QuotNo != null)
                    newInvoice.isQuotation = "Y";
                else
                {
                    newInvoice.isQuotation = "N";
                    newInvoice.QuotNo = "";
                }

                newInvoice.PONo = model.invoiceModel.PONo;

                if (newInvoice.PONo != null)
                    newInvoice.isPurchaseOrder = "Y";
                else
                {
                    newInvoice.isPurchaseOrder = "N";
                    newInvoice.PONo = "";
                }

                newInvoice.WONo = model.invoiceModel.WONo;

                if (newInvoice.WONo != null)
                    newInvoice.isWorkOrder = "Y";
                else
                {
                    newInvoice.isWorkOrder = "N";
                    newInvoice.WONo = "";
                }

                newInvoice.TotalAmount = model.RequestedTotal;
                newInvoice.IsValid = "Y";

                List<InvoiceItemModel> itemsList = GetInvoiceItemsList(newInvoice.InvoiceNo, quotModelList);

                bool isSuccess = SaveInvoice(newInvoice, itemsList);

                if(isSuccess == true)
                    return RedirectToAction("InvoiceConfirmation", new { invoiceNo = newInvoice.InvoiceNo });
                else
                    return RedirectToAction("InvoiceNotSuccessful", new { invoiceNo = newInvoice.InvoiceNo });
            }
            SaveState(model, selectedFM);
            return View(model);
        }

        public ActionResult InvoiceConfirmation(String invoiceNo)
        {
            ViewBag.Message = "Invoice - Successful";
            List<InvoiceItemModel> invoiceItems = invoiceRepository.GetInvoiceItems_ByInvoiceNo(invoiceNo);

            return View(invoiceItems);
        }

        public ActionResult InvoiceNotSuccessful(String invoiceNo)
        {
            ViewBag.Message = "Invoice - Unsuccessful";
            List<InvoiceItemModel> invoiceItems = invoiceRepository.GetInvoiceItems_ByInvoiceNo(invoiceNo);

            return View(invoiceItems);
        }

        public bool SaveInvoice(InvoiceModel invoice, List<InvoiceItemModel> invoiceItems)
        {
            bool isSuccess = false;

            try
            {
                #region Part I - To Database
                // (a) Save the invoice records into database
                invoiceRepository.Insert(invoice);
                invoiceRepository.Insert(invoiceItems);
                #endregion

                String[] fmSplit = invoice.InvoiceNo.Split('-');

                #region Part II - To Word
                FMModel fm = fmRepository.GetFM(fmSplit[0]);
                CompanyModel company = new CompanyModel();

                if (fm != null)
                    company = companyRepository.GetCompany(fm.CompanyName);
                invoiceDocument.GenerateInvoice(invoice, invoiceItems, fm, company);

                if(invoice.isDebitNote == "Y")
                    invoiceDocument.GenerateAttachmentTable(invoice, invoiceItems, fm, company);
                #endregion

                isSuccess = true;
            }
            catch(Exception e)
            {
                isSuccess = false;
            }

            return isSuccess;        
        }

        public List<InvoiceItemModel> GetInvoiceItemsList(String InvoiceNo, List<QuotationModel> srcList)
        {
            List<InvoiceItemModel> resultList = new List<InvoiceItemModel>();

            foreach(QuotationModel item in srcList)
            {
                InvoiceItemModel tempItem = new InvoiceItemModel();
                tempItem.InvoiceNo = InvoiceNo;
                tempItem.QuotationNo = item.QuotationNo;

                resultList.Add(tempItem);
            }

            return resultList;
        }

        void SaveState(QuotationInvoiceModel model, String FM)
        {
            //create comma delimited list of product ids
            model.SavedRequested = string.Join(",", model.RequestedQuotaionsSelectedList.Select(p => p.QuotationNo).ToArray());

            //Available products = All - Requested
            List<QuotationModel> tempList = GetAllAvailableQuotaionsList();
            List<String> requestedQuotationsNo = (from quotation in model.RequestedQuotaionsSelectedList
                                                  select quotation.QuotationNo).ToList();

            List<QuotationModel> resultList = GetAvailableQuotList(tempList, requestedQuotationsNo);

            model.AvailableQuotaionsSelectedList = resultList;

            model.fmList = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), FM);
        }

        public List<QuotationModel> GetAvailableQuotList(List<QuotationModel> srcList, List<String> selectedQuotNOs)
        {
            List<QuotationModel> resultList = new List<QuotationModel>();

            foreach(QuotationModel src in srcList)
            {
                bool isFound = false;

                foreach(String quotNo in selectedQuotNOs)
                {
                    if(src.QuotationNo == quotNo)
                    {
                        isFound = true;
                        break;
                    }
                }

                if (isFound == false)
                    resultList.Add(src);
            }

            return resultList;
        }

        void RemoveQuotations(QuotationInvoiceModel model, String FM)
        {
            if (model.RequestedSelected != null)
            {
                model.RequestedQuotaionsSelectedList.RemoveAll(p => model.RequestedSelected.Contains(p.QuotationNo));
                model.RequestedSelected = null;
                model.fmList = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), FM);
                model.fmListForFiltering = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), true);
                model.targetList = generalRepository.GetInvoiceTypesForDropDownList(Configuration.TargetToList);
            }
        }

        void AddQuotations(QuotationInvoiceModel model, String FM)
        {
            if (model.AvailableSelected != null)
            {
                var quotations = GetAllAvailableQuotaionsList().Where(p => model.AvailableSelected.Contains(p.QuotationNo));
                model.RequestedQuotaionsSelectedList.AddRange(quotations);
                model.AvailableSelected = null;
                model.fmList = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), FM);
                model.fmListForFiltering = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), true);
                model.targetList = generalRepository.GetInvoiceTypesForDropDownList(Configuration.TargetToList);
            }
        }

        void RestoreSavedState(QuotationInvoiceModel model, String FM)
        {
            model.RequestedQuotaionsSelectedList = new List<QuotationModel>();

            //get the previously stored items
            if (!string.IsNullOrEmpty(model.SavedRequested))
            {
                string[] quotationNos = model.SavedRequested.Split(',');
                var quotations = GetAllAvailableQuotaionsList().Where(p => quotationNos.Contains(p.QuotationNo));
                model.RequestedQuotaionsSelectedList.AddRange(quotations);
                model.fmList = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), FM);
                model.fmListForFiltering = fmRepository.GetFMsForDropDownList(fmRepository.GetAllFMs().OrderBy(x => x.FMID).ToList(), true);
                model.targetList = generalRepository.GetInvoiceTypesForDropDownList(Configuration.TargetToList);
            }
        }
	}
}